package interceptcrossing.ui;

import interceptcrossing.Abscissa;
import interceptcrossing.Intercept;
import interceptcrossing.Intersection;
import interceptcrossing.IntersectionFinder;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Collection;

/**
 * @author: Igor Botyan
 * @date: May 7, 2010
 */
public class DebugWindowDirector {


	private List<Listener> listeners = new LinkedList<Listener>();
	private List<Intercept> intercepts;
	private IntersectionFinder intersectionFinder;
	private Abscissa currentAbscissa;
	private Collection<Intercept> currentAboveIntercepts;
	private Collection<Intercept> currentUnderIntercepts;

	public DebugWindowDirector(List<Intercept> intercepts) {
		this.intercepts = new LinkedList<Intercept>(intercepts);
		this.intersectionFinder = new IntersectionFinder(this.intercepts);

		while (this.intersectionFinder.hasPreviousStep()) {
			this.intersectionFinder.previousStep();
		}

		this.intersectionFinder.addListener(new IntersectionFinder.Listener() {

			public void currentAbscissaChanged(Abscissa abscissa, Collection<Intercept> aboveIntercepts,
			                                   Collection<Intercept> underIntercepts) {
				currentAbscissa = abscissa;
				currentAboveIntercepts = aboveIntercepts;
				currentUnderIntercepts = underIntercepts;
				DebugWindowDirector.this.fireCurrentAbscissaChanged(abscissa, aboveIntercepts, underIntercepts);
			}
		});
	}

	public List<Intercept> getIntercepts() {
		return new LinkedList<Intercept>(this.intercepts);
	}

	public Set<Intersection> getIntersections() {
		return this.intersectionFinder.getIntersections();
	}

	public void addListener(Listener listener) {
		if (!this.listeners.contains(listener)) {
			this.listeners.add(listener);
			listener.currentAbscissaChanged(currentAbscissa, currentAboveIntercepts, currentUnderIntercepts);
		}
	}

	public void removeListener(Listener listener) {
		if (this.listeners.contains(listener)) {
			this.listeners.remove(listener);
		}
	}

	public boolean hasNextStep() {
		return this.intersectionFinder.hasNextStep();
	}

	public void nextStep() {
		this.intersectionFinder.nextStep();
	}

	public boolean hasPreviousStep() {
		return this.intersectionFinder.hasPreviousStep();
	}

	public void previousStep() {
		this.intersectionFinder.previousStep();
	}

	public void goToStart() {
		while (this.intersectionFinder.hasPreviousStep()) {
			this.intersectionFinder.previousStep();
		}
	}

	public void goToEnd() {
		while (this.intersectionFinder.hasNextStep()) {
			this.intersectionFinder.nextStep();
		}
	}

	private void fireCurrentAbscissaChanged(Abscissa abscissa, Collection<Intercept> aboveIntercepts,
			                                   Collection<Intercept> underIntercepts) {
		for (Listener listener : this.listeners) {
			listener.currentAbscissaChanged(abscissa, aboveIntercepts, underIntercepts);
		}
	}

	public static interface Listener {

		public void currentAbscissaChanged(Abscissa abscissa, Collection<Intercept> aboveIntercepts,
			                                   Collection<Intercept> underIntercepts);
	}
}
